package com.nervenets.shopping.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.nervenets.general.enumeration.Action;
import com.nervenets.general.service.GlobalSecurityService;
import com.nervenets.general.service.impl.TreeServiceImpl;
import com.nervenets.general.utils.SpringContextHolder;
import com.nervenets.general.utils.StringUtils;
import com.nervenets.general.web.params.Params;
import com.nervenets.shopping.enumeration.Gender;
import com.nervenets.shopping.event.DataOfUserEvent;
import com.nervenets.shopping.hibernate.dao.UserDao;
import com.nervenets.shopping.hibernate.dao.UserExtraDao;
import com.nervenets.shopping.hibernate.dao.UserWxIdDao;
import com.nervenets.shopping.hibernate.domain.user.User;
import com.nervenets.shopping.hibernate.domain.user.UserExtra;
import com.nervenets.shopping.hibernate.domain.user.UserWxId;
import com.nervenets.shopping.service.UserService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Slf4j
@Service
public class UserServiceImpl extends TreeServiceImpl<User, UserDao> implements UserService {
    @Resource
    private UserExtraDao userExtraDao;
    @Resource
    private UserWxIdDao userWxIdDao;
    @Resource
    private GlobalSecurityService globalSecurityService;

    @Override
    protected void before(Action action, User user, Params... params) {
        super.before(action, user, params);
        if (Action.delete.equals(action)) {
            user.setUnionId("removed");
            user.getWxIds().clear();
        }
    }

    @Override
    protected void after(Action action, User user, Params... params) {
        super.after(action, user, params);
        if (Action.add.equals(action)) {
            SpringContextHolder.publishEvent(new DataOfUserEvent(DataOfUserEvent.Type.newer, user.getId(), user.getId()));
        }
        if (Action.delete.equals(action)) {
            globalSecurityService.clearToken(user.getId());
            SpringContextHolder.publishEvent(new DataOfUserEvent(DataOfUserEvent.Type.newer, user.getId(), user.getId()));
        }
    }

    public User findByMobile(String mobile) {
        return dao.findByMobile(mobile);
    }

    public User findByOpenId(String openId) {
        final UserWxId byOpenId = userWxIdDao.findByOpenId(openId);
        return null == byOpenId ? null : byOpenId.getUser();
    }

    @Override
    public User findByUnionId(String unionId) {
        return dao.findByUnionId(unionId);
    }

    @Override
    public void saveUserWxId(User user, WxMpUser wxMpUser, String appId) {
        UserWxId byOpenId = userWxIdDao.findByOpenId(wxMpUser.getOpenId());
        if (null == byOpenId) {
            byOpenId = new UserWxId();
            byOpenId.setOpenId(wxMpUser.getOpenId());
            byOpenId.setUser(user);
            byOpenId.setAppId(appId);
        }
        byOpenId.setNickName(wxMpUser.getNickname());
        byOpenId.setAvatar(wxMpUser.getHeadImgUrl());
        byOpenId.setGender(1 == wxMpUser.getSex() ? Gender.male : Gender.female);
        userWxIdDao.save(byOpenId);
    }

    @Override
    public UserWxId findUserWxId(User user, String appId) {
        return userWxIdDao.findTop1ByUserAndAppId(user, appId);
    }

    @Override
    public void saveUserExtra(User user, String key, String value) {
        if (!StringUtils.isEmpty(key) && !StringUtils.isEmpty(value)) {
            UserExtra extra = userExtraDao.findByUserAndField(user, key);
            if (null == extra) extra = new UserExtra();
            extra.setUser(user);
            extra.setField(key);
            extra.setValue(value);
            userExtraDao.save(extra);
        }
    }

    @Override
    public UserExtra findUserExtra(User user, String key) {
        return userExtraDao.findByUserAndField(user, key);
    }

    @Override
    public void updateInviteCount(long count, long id) {
        dao.updateInviteCount(count, id);
    }

    @Override
    public void updateGroupCountAndTime(long userId, long groupCount, long lastGroupTime) {
        dao.updateGroupCountAndTime(userId, groupCount, lastGroupTime);
    }

    public void saveUserExtras(User user, JSONObject extraObj) {
        extraObj.forEach((key, value) -> {
            if (!StringUtils.isEmpty(key) && null != value) {
                this.saveUserExtra(user, key, String.valueOf(value));
            }
        });
    }
}
